#!/usr/bin/python
# -*- coding: utf-8 -*-

import argparse
import os
import pwd
import crypto
from logger import Logger 


class GroupSignature:
    keySize = 512
    def __init__(self):
        try:
            invocation = argparse.ArgumentParser()
            invocation.add_argument("cmd", nargs="+", metavar = "CMD", 
                       help = "command string")
            invocation.add_argument("-v", action = "store_true", dest = 
                      "verbose", help = "verbose mode")
            invocation.add_argument("-f", action = "store_true", dest = 
                      "fromFile", help = "get users from file")
            args = invocation.parse_args()
            
            if len(args.cmd) < 3:
                invocation.error("Incomplete command string")
            args.debug = False
            Logger.init(args)
            
            if   args.cmd[0] == "create":
                self.create(args.cmd[1:], args.fromFile)
            elif args.cmd[0] == "sign":
                self.sign(args.cmd[1:])
            elif args.cmd[0] == "verify":
                self.verify(args.cmd[1:])
            elif args.cmd[0] == "open":
                self.open(args.cmd[1:])
            else:
                invocation.error("Invalid command {}".format(args.cmd[0]))
                
        except KeyboardInterrupt:
            pass
        except Exception as e:
            Logger.error(e)
            
    def create(self, cmd, fromFile):
        group = cmd[0]
        if fromFile:
            f = open(cmd[1])
            users = f.read().split("\n")
            f.close()
        else:
            users = cmd[1:]
        
        gpk, gmsk, gsk = crypto.GKg(self.keySize, users[1:])
        
        user_dir = pwd.getpwnam(users[0])[5]
        path = os.path.join(user_dir, ".gsig")
        if not os.path.isdir(path):
            os.mkdir(path, 0700)
        uid = pwd.getpwnam(users[0])[2]
        gid = pwd.getpwnam(users[0])[3]
        os.chown(path, uid, gid)
            
        path = os.path.join(path, "{}.gpk".format(group))
        f = open(path, "w")
        f.write(str(gpk))
        f.close()
        os.chown(path, uid, gid)
        os.chmod(path, 0600)
        
        path = os.path.join(user_dir, ".gsig")
        path = os.path.join(path, "{}.gmsk".format(group))
        f = open(path, "w")
        f.write(str(gmsk))
        f.close()
        os.chown(path, uid, gid)
        os.chmod(path, 0600)
        
        for user in users[1:]:
            user_dir = pwd.getpwnam(user)[5]
            path = os.path.join(user_dir, ".gsig")
            if not os.path.isdir(path):
                os.mkdir(path, 0700)
            uid = pwd.getpwnam(user)[2]
            gid = pwd.getpwnam(user)[3]
            os.chown(path, uid, gid)
            
            path = os.path.join(path, "{}.gpk".format(group))    
            f = open(path, "w")
            f.write(str(gpk))
            f.close()
            os.chown(path, uid, gid)
            os.chmod(path, 0600)
            
            path = os.path.join(user_dir, ".gsig")
            path = os.path.join(path, "{}.gsk".format(group))
            f = open(path, "w")
            f.write(str(gsk[user]))
            f.close()
            os.chown(path, uid, gid)
            os.chmod(path, 0600)
    
    def sign(self, cmd):
        group = cmd[0]
        user_dir = pwd.getpwuid(os.getuid())[5]
        
        path = os.path.join(user_dir, ".gsig", "{}.gsk".format(group))
        f = open(path, "r")
        gsk = crypto.GroupSecretKey(b64 = f.read())
        f.close()
        
        path = cmd[1]
        f = open(path, "r")
        m = f.read()
        f.close
        
        sigma = crypto.GSig(m, gsk)
        
        path += ".gsig"
        f = open(path, "w")
        f.write(sigma)
        f.close()
        
    def verify(self, cmd):
        group = cmd[0]
        user_dir = pwd.getpwuid(os.getuid())[5]
        
        path = os.path.join(user_dir, ".gsig", "{}.gpk".format(group))
        f = open(path, "r")
        gpk = crypto.GroupPublicKey(b64 = f.read())
        f.close()
        
        path = cmd[1]
        f = open(path, "r")
        m = f.read()
        f.close
        
        path += ".gsig"
        f = open(path, "r")
        sigma = f.read()
        f.close()
        
        if crypto.GVf(m, sigma, gpk):
            Logger.message("OK!")
        else:
            Logger.message("Verfication failed!")
    
    def open(self, cmd):
        group = cmd[0]
        user_dir = pwd.getpwuid(os.getuid())[5]
        
        path = os.path.join(user_dir, ".gsig", "{}.gpk".format(group))
        f = open(path, "r")
        gpk = crypto.GroupPublicKey(b64 = f.read())
        f.close()
        
        path = os.path.join(user_dir, ".gsig", "{}.gmsk".format(group))
        if not os.path.isfile(path):
            Logger.message("You are not authorised to open signature for group {}".format(group))
            return
        f = open(path, "r")
        gmsk = crypto.GroupManagerSecretKey(b64 = f.read())
        f.close()
        
        path = cmd[1]
        f = open(path, "r")
        m = f.read()
        f.close
        
        path += ".gsig"
        f = open(path, "r")
        sigma = f.read()
        f.close()
        
        user = crypto.GOpen(m, sigma, gpk, gmsk)
        if user is not None:
            Logger.message(user)
        else:
            Logger.message("Verification failed!")
        
GroupSignature()        